/**
 * Copyright (c) 2011-2015 1lifes.com
 * HSJ java-handlersocket
 * Id: AbstractPacket.java
 */
package com.elifes.hsj.packet;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;

import com.elifes.hsj.util.Constants;

/**
 * 描述：
 * @author yangqiang
 * @createtime 2011-11-12上午11:51:40
 *
 */
public abstract class AbstractPacket implements IPacket{
	private static final Logger logger = Logger.getLogger(AbstractPacket.class);

	public static final String OPERATOR_AUTH = "A";
	public static final String OPERATOR_OPEN_INDEX = "P";
	public static final String OPERATOR_INSERT = "+";
	public static final String OPERATOR_UPDATE = "U";
	public static final String OPERATOR_DELETE = "D";
	
	public static final String TAB_TOKEN = "\t";
	public static final String SPACE_TOKEN = " ";
	public static final String END_TOKEN = "\r\n";
	
	protected String encoding = Constants.DEFAULT_ENCODING;
	protected PacketEnum type;
	
	protected String indexId;
	protected String dbName;
	protected Object result;
	protected String exceptionMessage;
	
	private final CountDownLatch latch;
	
	public AbstractPacket(){
		this.latch = new CountDownLatch(1);
	}
	
	public String getIndexId(){
		return indexId;
	}
	
	public String getDbName(){
		return dbName;
	}
	
	public String encode(){
		StringBuilder reqMsg = new StringBuilder();
		encodeHeader(reqMsg);
		encodeBody(reqMsg);
		encodeEnd(reqMsg);
		
		return reqMsg.toString();
	}
	
	public Object decode(){
		return getResult();
	}
	
	protected abstract void encodeHeader(StringBuilder reqMsg);

	protected abstract void encodeBody(StringBuilder reqMsg);

	protected void encodeEnd(StringBuilder reqMsg) {
		reqMsg.append(END_TOKEN);
	}
	
	protected String autoAppendSpace(String content){
		return content + SPACE_TOKEN;
	}
	
	protected String autoAppendTab(String content){
		return content + TAB_TOKEN;
	}
	
	public boolean await(int timeout){
		try {
			return latch.await(timeout, TimeUnit.MILLISECONDS);
		} catch (InterruptedException e) {
			logger.error("hs packet await interrupted!", e);
			return false;
		}
	}
	
	public void await(){
		try {
			latch.await();
		} catch (InterruptedException e) {
			logger.error("hs packet await interrupted!", e);
		}
	}
	
	public Object getResult(){
		return result;
	}
	
	public void setResult(Object result){
		this.result = result;
		//other thread can run
		latch.countDown();
	}
	
	public void setExceptionMessage(String exceptionMessage){
		this.exceptionMessage = exceptionMessage;
	}

	public String getExceptionMessage(){
		return exceptionMessage;
	}
	
	public PacketEnum getType(){
		return type;
	}

}
